home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-04
/
ddj1291.zip
/
STAT.ZIP
/
SOURCE.ZIP
/
PAMSDOS.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-05-09
|
10KB
|
309 lines
/*
** File: pamsdos.c
**
** Copyright 1990
** Fred Motteler and Applied Microsystems Corporation
** All Rights Reserved
**
** Description: Utility functions used by the MS-DOS version of the
** statistical performance analysis package.
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include "padef.h"
/*
** Function: int main( argcN, argvAS )
**
** Description: MS-DOS based statistical performance analysis program.
**
** Command line arguments:
**
** pamsdos prog.map prog.cfg prog.exe options
**
** Where: prog.map memory map for program
** prog.cfg memory map configuration
** prog.exe program to run
** options command options for the program to run
*/
int
main( argcN, argvAS )
int argcN;
char *argvAS[];
{
int errorN; /* Error code */
unsigned int segmentW; /* Starting load address of program to run */
unsigned int offsetW;
unsigned long originL;
int processedN; /* Number of map globals processed */
int i; /* General index */
FILE *mapFP; /* Map file to read */
FILE *formatFP; /* File with map file format information */
char commandAC[PA_LINE_LEN]; /* Complete command line for program */
int pagelinesN; /* Number of lines on output page, 0 if
* continuous, -1 if no display output, else
* n if n lines per page. */
FILE *listFP; /* Results output file */
char listAB[80]; /* Optional results listing file path/name */
char pagelinesAB[8]; /* String for number of lines/page */
printf("pamsdos - Statistical performance analysis tool for MS-DOS\n");
printf("Version %s\n", PA_VERSION);
printf("Copyright (C) 1990 Fred Motteler and Applied Microsystems Corporation\n");
if (argcN < 4)
{
printf("Usage: pamsdos prog.map prog.cfg prog.exe [options]\n");
printf(" Where: prog.map memory map for program\n");
printf(" prog.cfg memory map configuration file\n");
printf(" prog.exe program to run\n");
printf(" [options] command line options for the program to run\n");
exit(-100);
}
/* Determine where the program to run is to be located. */
if ((errorN = pa_locate(&segmentW, &offsetW)) != 0)
{
pa_error(errorN);
exit(errorN);
}
/* Calculate origin of program. Room must be allowed for memory
* malloc()'d off the heap. */
originL = (unsigned long) (segmentW + 1);
originL <<= 4;
originL += (unsigned long) (offsetW - 2);
originL += (unsigned long) (PA_BUFLEN << 2);
if ((pa_debugN & PA_GENERAL) != 0)
{
printf("program start segment:offset %x:%x\n", segmentW, offsetW);
printf(" linear address %lx\n",originL);
}
/* Get the complete command line to invoke the program. */
strcpy(commandAC, argvAS[3]);
if (argcN > 4)
{
for (i = 4; i < argcN; i++)
{
strcat(commandAC," ");
strcat(commandAC,argvAS[i]);
}
}
/* Run the program and collect samples. */
printf("Starting %s\n", argvAS[3]);
if ((errorN = pa_pcsample(commandAC, PA_SAMPLE, PA_BUFLEN)) != 0)
{
pa_error(errorN);
exit(errorN);
}
/* Read in the configuration file to get map format information and
* to get number of lines / display page and option listing file. */
if ((formatFP = fopen(argvAS[2], "r")) == (FILE *) NULL)
{
pa_error(PA_NO_CFG_E);
exit(PA_NO_CFG_E);
}
/* Read in display lines, and optional output file configuration data
* from the configuration file. */
if (((errorN = paconfig(formatFP, PA_PAGELINES, pagelinesAB)) != 0) ||
((errorN = paconfig(formatFP, PA_LISTFILE, listAB)) != 0))
{
pa_error(errorN);
fclose(formatFP);
exit(errorN);
}
/* Determine the number of lines/page to display */
if (sscanf(pagelinesAB, "%d", &pagelinesN) != 1)
{
pa_error(PA_BAD_ARG_E);
fclose(formatFP);
exit(PA_BAD_ARG_E);
}
/* Open the optional listing file */
if (listAB[0] == '\0')
listFP = (FILE *) NULL;
else if ((listFP = fopen(listAB, "w")) == (FILE *) NULL)
{
pa_error(PA_NO_LST_E);
fclose(formatFP);
exit(PA_NO_LST_E);
}
/* Read the program's memory map and create "bins" for the program
* counter samples. */
if ((mapFP = fopen(argvAS[1], "r")) == (FILE *) NULL)
{
pa_error(PA_NO_MAP_E);
fclose(mapFP);
exit(PA_NO_MAP_E);
}
if ((errorN = pardmap(mapFP, formatFP, originL, &processedN)) != 0)
{
pa_error(errorN);
fclose(mapFP);
fclose(formatFP);
exit(errorN);
}
/* Process the samples and sort the bins according to the PC hits in
* each bin. */
printf("Processing samples\n");
if ((errorN = pa_bstuff(PA_SAMPLE, patableAHP, &processedN)) != 0)
{
pa_error(errorN);
fclose(mapFP);
fclose(formatFP);
exit(errorN);
}
/* Display the results */
padisply(patableAHP, processedN, pagelinesN, listFP);
fclose(mapFP);
fclose(formatFP);
exit(0);
}
/*
** Function: int pa_locate(unsigned int *segmentPW, unsigned int *offsetPW)
**
** Description: This function figures out where in memory the program to be
** analyzed is to be run.
**
** MS-DOS executables are dynamically located at runtime.
** In order to avoid the complexity of writing a DOS ".exe"
** loader program, a simpler approach is used here.
**
** This function uses the ANSI system() library function to
** execute a trial program, "pawhere.exe" that writes its
** starting code segment and offset to a temporary file
** "pawhere.tmp". After "pawhere.exe" has finished, this
** function opens the temporary file and reads the starting
** segment and offset value.
**
** It is assumed that the desired program to be tested will
** have the same starting code segment and offset.
**
** If all operations were successful, then 0 is returned.
** Otherwise a non-zero error code will be returned.
*/
int
pa_locate(segmentPW, offsetPW)
unsigned int *segmentPW;
unsigned int *offsetPW;
{
FILE *fp;
/* First figure out where the program will be loaded. Run "pawhere.exe"
* via a system() function call. */
if ((system("pawhere")) != 0)
return(PA_NO_WHERE_E);
/* Read in the result of whereami.tmp. */
if ((fp = fopen("pawhere.tmp", "r")) == (FILE *) NULL)
return(PA_NO_TMP_E);
if ((fscanf(fp, "%x %x", segmentPW, offsetPW)) != 2)
return(PA_BAD_TMP_E);
fclose(fp);
if (remove("pawhere.tmp") != 0)
return(PA_TMP_RM_E);
return(0);
}
/*
** Function: int pa_pcsample(char *programS, char *sampfileS, int samplesN)
**
** Description: This function runs the program (entire command line) pointed
** to by programS, while sampling its program counter every
** PC clock tick. Up to samplesN program counter samples are
** collected, and then written out in binary format to the file
** sampfileS.
*/
int
pa_pcsample(programS, sampfileS, samplesN)
char *programS; /* Command line of program to run */
char *sampfileS; /* File to use to write out pc samples */
int samplesN; /* Maximum number of samples to collect */
{
unsigned long *pcbufferPL; /* Word pointer to local pc sample buffer */
unsigned int *pcbufferPW; /* Long pointer to local pc sample buffer */
unsigned long *pcorgPL; /* Original copy of pointer to pc sample buf */
unsigned int segmentW; /* Starting segment of program to run */
unsigned int offsetW; /* Starting offset of program to run */
int handleN; /* pc sample file handle */
unsigned long sampleL; /* segment:offset sample converted to linear */
int i; /* general index */
/* Grab memory for the sample buffer */
if ((pcbufferPL = (unsigned long *) malloc((4*samplesN)))
== (unsigned long *) NULL)
return(PA_NO_MEM_E);
/* Copy buffer pointer to allow word (int) access as well as long acess. */
pcbufferPW = (unsigned int *) pcbufferPL;
pcorgPL = pcbufferPL;
/* Start CS:IP sampling */
paopen(pcbufferPW, samplesN);
/* Run the desired program. */
if (system(programS) != 0)
{
paclose();
return(PA_NO_EXEC_E);
}
/* Stop sampling */
samplesN = paclose();
/* Convert the samples from offsetW:segment to linear addresses relative
* to the origin of the loaded program. */
if ((pa_debugN & PA_GENERAL) != 0)
printf("pa_pcsample: number of samples: %d\n", samplesN);
for (i = 0; i < samplesN; i++)
{
/* Read segment:offset value from the table. */
offsetW = *pcbufferPW++;
segmentW = *pcbufferPW++;
if ((pa_debugN & PA_GENERAL) != 0)
printf("pa_pcsample: sample segment:offset %x:%x\n",
segmentW,offsetW);
/* Convert it to a linear address. */
sampleL = ((unsigned long) offsetW)
+ (((unsigned long) segmentW) << 4);
/* Write the linear address back to the table. */
*pcbufferPL++ = sampleL;
if ((pa_debugN & PA_GENERAL) != 0)
printf("pa_pcsample: linear sample %lx\n",sampleL);
}
/* Write the samples to a binary file. */
if ((handleN = open (sampfileS, (O_CREAT | O_WRONLY | O_RAW), 0))
== (-1))
{
free(pcorgPL);
return(PA_NO_PC_FILE_E);
}
if ((write( handleN, ((char *) pcorgPL), (samplesN << 2)))
!= (samplesN << 2))
{
close(handleN);
free(pcorgPL);
return(PA_NO_PC_WR_E);
}
close(handleN);
free(pcorgPL);
return(0);
}